#pragma once
#include "Socket.h"
#include<poll.h>

class PollServer
{
private:
    int listenSock_;
    int port_;
private:
    void ClearPollfds(struct pollfd fds[],int num,int default_id)
    {
        for(int i = 0; i < num; ++i)
        {
            fds[i].fd = default_id;
            fds[i].events = 0;
            fds[i].revents = 0;
        }
    }
    bool SetPollfds(struct pollfd fds[],int num,int fd)
    {
        for(int i = 0; i < num; ++i)
        {
            if(fds[i].fd == -1)
            {
                fds[i].fd = fd;
                fds[i].events |= POLLIN;
                return true;
            }
        }
        return false;
    }
    void UnSetPollfds(struct pollfd fds[],int pos)
    {
        fds[pos].fd = -1;
        fds[pos].events = fds[pos].revents = 0;
    }
public:
    PollServer(int port):port_(port){}
    void Init()
    {
        listenSock_ = Socket::SocketCreate();
        Socket::SocketBind(listenSock_,port_);
        Socket::SocketListen(listenSock_,5);
    }
    void Run()
    {
        struct pollfd fds[128];
        ClearPollfds(fds,128,-1);//清空数组中的所有位置
        SetPollfds(fds,128,listenSock_);//添加监听套接字到struct pollfd数组中
        while(true)
        {
            switch(poll(fds,128,-1))//第三个参数为-1，即阻塞等待
            {
                case 0:
                    std::cout << "timeout..." << std::endl;
                    break;
                case -1:
                    std::cerr << "poll error" << std::endl;
                    break;
                default:
                    HandlerEvent(fds,128);
                    break;
            }
        }
    }
private:
    void HandlerEvent(struct pollfd fds[],int num)
    {
        for(int i = 0; i < num; ++i)
        {
            if(fds[i].fd == -1)
                continue;
            if(fds[i].fd == listenSock_ && fds[i].revents&POLLIN)
            {
                struct sockaddr_in peer;
                socklen_t len = sizeof(peer);
                int sock = accept(listenSock_,(struct sockaddr*)&peer,&len);
                if(sock < 0)
                {
                    std::cout << "accept error" << std::endl;
                    continue;
                }
                std::string client_ip = inet_ntoa(peer.sin_addr);
                int client_port = ntohs(peer.sin_port);
                std::cout << "Get a new link[" << client_ip << ":" << client_port <<"]" << std::endl;
                
                if(!SetPollfds(fds,128,sock))
                {
                    close(sock);
                    std::cout  <<"poll server is full,close sock " << std::endl;
                }
            }
            else if(fds[i].revents&POLLIN)
            {
                char buffer[1024];
                int size = read(fds[i].fd,buffer,sizeof(buffer)-1);
                if(size > 0)
                {
                    buffer[size-2] = '\0';//telnet即使敲回车也会有2个字节
                    std::cout << "echo:" << buffer << std::endl;
                }
                else if(size == 0)
                {
                    std::cout << "client quit" << std::endl;
                    close(fds[i].fd);
                    UnSetPollfds(fds,i);
                }
                else
                {
                    std::cerr << "read error" << std::endl;
                    close(fds[i].fd);
                    UnSetPollfds(fds,i);
                }
            }
        }
    }
public:
    ~PollServer()
    {
        if(listenSock_ >= 0)
            close(listenSock_);
    }
};